import { execSync } from 'child_process';
import fs from 'fs';
import { url } from 'inspector';
import jszip from 'jszip'

/**
 * @type {ssh2.ConnectConfig}
 */
const FRAMEWORK_PATH = "./";
const LOCAL_PATH = "./build";

/**
 * @callback foreachCallback
 * @param {fs.Dirent} dirent
 * @param {string} path
 */
/**
 * 
 * @param {string} dirPath 
 * @param {string} addPath 
 * @param {foreachCallback} callback 
 */
const DirFileForeach = async function (dirPath, addPath, callback) {
  const fsDir = fs.opendirSync(dirPath + "/" + addPath);
  let childDirent = fsDir.readSync();
  while (childDirent) {
    let pathDelta = addPath;
    if (pathDelta !== "") {
      pathDelta += "/";
    }
    if (childDirent.isDirectory()) {
      await DirFileForeach(dirPath, pathDelta + childDirent.name, callback);
    }
    else {
      callback(childDirent, pathDelta + childDirent.name);
    }
    childDirent = fsDir.readSync();
  }
  fsDir.closeSync();
};

class BuildFrameConfig {
  framePath = "";
  gamePath = "";
  bundlePath = "";
};

/**
 * 构建配置
 */
class BuildConfig {
  buildId = 0;
  lastBuildUid = "";
};

/**
 * 游戏配置
 */
export class GameLoadingConfig {
  inGame = "BoxLoading"; // 引擎载入后的LOADING
  bgUrl = "bg.jpg";
  bgInAsset = "";
  hasLabel = true;
  hasIcon = true;
};
export class GameConfig {
  //游戏唯一名字 英文字母 PingPongGame / ping_pong_game
  key = "";
  //游戏名字
  name = "";
  //游戏描述
  desc = "";
  //游戏版本 
  version = "";
  //游戏版本时间戳
  timestamp = "";
  /**
   * @type {"Landscape" | "Vertical"}
   */
  screen = "Vertical";
  //开始页面
  defaultStartPage = "";
  //BUNDLE包内容
  bundleConfigCol = {};
  //使用微信API
  hasWeiXin = false;

  /**
   * @type {string[]}
   */
  h5Assets = [];
  /**
   * 载入配置
   * @type { GameLoadingConfig }
   */
  loading = null;
};

/** 获取随机字符串，最大15位。 */
export class Uid {
  static get0x(x) {
    return Math.floor(Math.random() * x + 1);
  }
  static getUid(digit = 15) {
    if (digit >= 15) {
      digit = 15;
    }
    return ("" + (new Date().getTime()) + Uid.get0x(99)).slice(15 - digit, 15);
  }
};

const PackRec = async (zf, path) => {
  const fsDir = fs.opendirSync(path);
  let childDirent = fsDir.readSync();
  while (childDirent) {
    if (childDirent.isDirectory()) {
      let czf = zf.folder(childDirent.name);
      await PackRec(czf, path + childDirent.name + "/");
    }
    else {
      zf.file(childDirent.name, fs.readFileSync(path + childDirent.name));
    }
    childDirent = fsDir.readSync();
  }
  fsDir.closeSync();
};

const CompressRec = async (path) => {
  const fsDir = fs.opendirSync(path);
  let childDirent = fsDir.readSync();
  while (childDirent) {
    if (childDirent.isDirectory()) {
      await CompressRec(path + childDirent.name + "/");
    }
    else {
      if (childDirent.name.split(".")[1] == "png") {
        await execSync(`pngquant -f --ext .png --quality 10-90 --speed 1 "${path + childDirent.name}"`);
        console.log(`pngquant: 压缩图片"${path + childDirent.name}"`);
      }
    }
    childDirent = fsDir.readSync();
  }
};

//=======================================================================
let argvs = process.argv;
console.log("参数:", argvs.slice(2));
const BUILD_TARGET = argvs[2];
const USE_UID = argvs[3] === "yes";

let frameConfig = new BuildFrameConfig();
let config = new BuildConfig();
let gameConfig = new GameConfig();

if (!fs.existsSync("./buildFrame.json")) {
  fs.writeFileSync("./buildFrame.json", JSON.stringify(config));
}
else {
  let buf = await fs.readFileSync("./buildFrame.json");
  let configStr = buf.toString();
  Object.assign(frameConfig, JSON.parse(configStr));
}
//一些路径
let framePath = frameConfig.framePath.replace("{{protocol}}", BUILD_TARGET == "test" ? "http://local." : "https://");
let gamePath = framePath + frameConfig.gamePath;
// let bundlePath = config.framePath.replace("{{protocol}}", BUILD_TARGET == "test" ? "local." : "");


if (!fs.existsSync("./buildBundleGame.json")) {
  fs.writeFileSync("./buildBundleGame.json", JSON.stringify(config));
}
else {
  let buf = fs.readFileSync("./buildBundleGame.json");
  let configStr = buf.toString();
  Object.assign(config, JSON.parse(configStr));
}

if (!BUILD_TARGET) {
  console.log("请输入参数: test/res");
  process.exit(0);
}

let gameConfigUrl = "";
switch (BUILD_TARGET) {
  case "res":
    {
      gameConfigUrl = "./assets/bundle/game_config_res.json"
    }
    break;
  case "test":
    {
      gameConfigUrl = "./assets/bundle/game_config_test.json"
    }
    break;
  default:
    console.log("BUILD_TARGET参数输入错误");
    process.exit(0);
    break;
}

try {
  //读取gameConfig
  let buf = fs.readFileSync(gameConfigUrl);
  let gameConfigStr = buf.toString();
  Object.assign(gameConfig, JSON.parse(gameConfigStr));
}
catch (e) {
  console.log("读取gameConfig失败，找不到配置");
  process.exit(0);
}

//复制bundle文件到build/[GAME_KEY]
config.lastBuildUid = Uid.getUid(10);
let gameKey = gameConfig.key;

if (USE_UID) {
  console.log("Uid:", config.lastBuildUid);
  gameKey += config.lastBuildUid;
}
let gamePathLocal = `${LOCAL_PATH}/${gameKey}`;
fs.mkdirSync(`${gamePathLocal}`);

for (let key in gameConfig.bundleConfigCol) {
  fs.mkdirSync(`${gamePathLocal}/${key}`);
  //复制文件。
  let copyStatment = `xcopy /y /c /s /h /r ` + `"${LOCAL_PATH}\\web-mobile\\assets\\${key}\\*.*" "${gamePathLocal}\\${key}\\" `.replaceAll("./", "").replaceAll("/", "\\");
  execSync(copyStatment);

  //配置包URL，让包成为远程包
  let bundleConfig = gameConfig.bundleConfigCol[key];
  if (!bundleConfig.url) {
    bundleConfig.url = gamePath + "/" + gameKey;
  }
}

//写配置
fs.writeFileSync(`${gamePathLocal}/config.json`, JSON.stringify(gameConfig));
//复制静态资源
if (gameConfig.h5Assets) {
  gameConfig.h5Assets.forEach(url => {
    if (url[url.length - 1] == "/" || url[url.length - 1] == "\\") {
      //文件夹
      let copyStatment = `echo d| xcopy /y /c /s /h /r ` + `"${url}" "${gamePathLocal}\\${url}" `.replaceAll("./", "").replaceAll("/", "\\");
      console.log("静态资源： " + copyStatment);
      execSync(copyStatment);
    }
    else {
      //文件。
      let copyStatment = `echo f| xcopy /y /c /s /h /r ` + `"${url}" "${gamePathLocal}\\${url}" `.replaceAll("./", "").replaceAll("/", "\\");
      console.log("静态资源： " + copyStatment);
      execSync(copyStatment);
    }
  });
}
if (gameConfig.loading.bgInAsset) {
  let copyStatment = `echo f| xcopy /y /c /s /h /r ` + `"${FRAMEWORK_PATH}\\${gameConfig.loading.bgInAsset}" "${gamePathLocal}\\${gameConfig.loading.bgUrl}" `.replaceAll("./", "").replaceAll("/", "\\");
  console.log("静态资源： " + copyStatment);
  execSync(copyStatment);
}

config.buildId++;
fs.writeFileSync("./buildBundleGame.json", JSON.stringify(config));

//压缩
await CompressRec(`${gamePathLocal}/`);

//打包
let zipPath = `${LOCAL_PATH}/${BUILD_TARGET}-${gameKey}.zip`;
{
  const zip = new jszip();
  const zf = zip.folder(gameKey);
  await PackRec(zf, `${gamePathLocal}/`);
  let content = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
  fs.writeFileSync(zipPath, content);
}

console.log("完成：", zipPath);
process.exit(0);